package com.heyige.facade;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heyige.common.RedisConstant;
import com.heyige.dto.AdminDto;
import com.heyige.dto.UserDto;
import com.heyige.entity.Admin;
import com.heyige.entity.User;
import com.heyige.entity.UserQuota;
import com.heyige.exception.BusinessException;
import com.heyige.exception.ErrorCode;
import com.heyige.mapper.AdminMapper;
import com.heyige.service.UserQuotaService;
import com.heyige.service.UserService;
import com.heyige.util.JwtUtil;
import com.heyige.util.RedisUtil;

import cn.hutool.crypto.digest.DigestUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserFacade {

    private final JwtUtil jwtUtil;
    private final UserService userService;
    private final UserQuotaService userQuotaService;
    private final AdminMapper adminMapper;

    public UserDto.LoginResponse login(UserDto.LoginRequest loginRequest) {
        String username = loginRequest.getUsername();
        String password = loginRequest.getPassword();

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username)
                .or()
                .eq(User::getEmail, username)
                .or()
                .eq(User::getPhone, username);

        User user = userService.getOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        if (!DigestUtil.bcryptCheck(password, user.getPassword())) {
            throw new BusinessException(ErrorCode.USER_PASSWORD_ERROR);
        }
        if (user.getStatus().equals(User.UserStatus.INACTIVE.toString())) {
            throw new BusinessException(ErrorCode.USER_DISABLED);
        }
        // 更新登录信息
        user.setLastLoginTime(LocalDateTime.now());
        user.setLoginCount(user.getLoginCount() + 1);
        userService.updateById(user);
        // 构建响应
        UserDto.LoginResponse response = new UserDto.LoginResponse();
        response.setToken(jwtUtil.generateToken(user.getId(), user.getUsername()));
        response.setUserId(user.getId());
        response.setUsername(user.getUsername());
        response.setEmail(user.getEmail());
        response.setPhone(user.getPhone());
        response.setAvatar(user.getAvatar());
        return response;
    }

    public User register(UserDto.RegisterRequest registerRequest) {
        String username = registerRequest.getUsername();
        String email = registerRequest.getEmail();
        String phone = registerRequest.getPhone();
        String password = registerRequest.getPassword();
        // 检查用户名是否已存在
        LambdaQueryWrapper<User> usernameQueryWrapper = new LambdaQueryWrapper<>();
        usernameQueryWrapper.eq(User::getUsername, username);
        if (userService.getOne(usernameQueryWrapper) != null) {
            throw new BusinessException(ErrorCode.USER_NAME_ALREADY_EXISTS);
        }
        // 检查邮箱是否已存在
        if (email != null) {
            LambdaQueryWrapper<User> emailQueryWrapper = new LambdaQueryWrapper<>();
            emailQueryWrapper.eq(User::getEmail, email);
            if (userService.getOne(emailQueryWrapper) != null) {
                throw new BusinessException(ErrorCode.USER_EMAIL_EXISTS);
            }
        }
        // 检查手机号是否已存在
        if (phone != null) {
            LambdaQueryWrapper<User> phoneQueryWrapper = new LambdaQueryWrapper<>();
            phoneQueryWrapper.eq(User::getPhone, phone);
            if (userService.getOne(phoneQueryWrapper) != null) {
                throw new BusinessException(ErrorCode.USER_PHONE_EXISTS);
            }
        }
        // 创建用户
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        user.setPhone(phone);
        user.setPassword(DigestUtil.bcrypt(password));
        user.setStatus(User.UserStatus.ACTIVE.toString());
        user.setLoginCount(0);
        user.setCreatedAt(LocalDateTime.now());
        userService.save(user);
        // 创建用户额度
        UserQuota userQuota = new UserQuota();
        userQuota.setUserId(user.getId());
        userQuotaService.save(userQuota);
        log.info("用户注册成功: {}", username);
        return user;
    }


    public User updateUser(Long userId, UserDto userDto) {
        User user = userService.getById(userId);

        if (userDto.getEmail() != null) {
            // 检查邮箱是否已被其他用户使用
            if (!user.getEmail().equals(userDto.getEmail())) {
                LambdaQueryWrapper<User> emailQueryWrapper = new LambdaQueryWrapper<>();
                emailQueryWrapper.eq(User::getEmail, userDto.getEmail());
                if (userService.getOne(emailQueryWrapper) != null) {
                    throw new BusinessException(ErrorCode.USER_EMAIL_EXISTS);
                }
            }
            user.setEmail(userDto.getEmail());
        }

        if (userDto.getPhone() != null) {
            // 检查手机号是否已被其他用户使用
            if (!user.getPhone().equals(userDto.getPhone())) {
                LambdaQueryWrapper<User> phoneQueryWrapper = new LambdaQueryWrapper<>();
                phoneQueryWrapper.eq(User::getPhone, userDto.getPhone());
                if (userService.getOne(phoneQueryWrapper) != null) {
                    throw new BusinessException(ErrorCode.USER_PHONE_EXISTS);
                }
            }
            user.setPhone(userDto.getPhone());
        }

        if (userDto.getAvatar() != null) {
            user.setAvatar(userDto.getAvatar());
        }

        userService.updateById(user);
        return user;
    }

    public void changePassword(Long userId, String oldPassword, String newPassword) {
        User user = userService.getById(userId);


        if (!DigestUtil.bcryptCheck(oldPassword, user.getPassword())) {
            throw new BusinessException(ErrorCode.USER_PASSWORD_ERROR);
        }

        user.setPassword(DigestUtil.bcrypt(oldPassword));
        userService.updateById(user);

        log.info("用户修改密码成功: {}", user.getUsername());
    }

    public void bindWechat(Long userId, String wxOpenid, String wxUnionid) {
        User user = userService.getById(userId);
        // 检查微信是否已被绑定
        LambdaQueryWrapper<User> wxQueryWrapper = new LambdaQueryWrapper<>();
        wxQueryWrapper.eq(User::getWxOpenid, wxOpenid);
        if (userService.getOne(wxQueryWrapper) != null) {
            throw new BusinessException(ErrorCode.WX_ALREADY_BIND);
        }
        user.setWxOpenid(wxOpenid);
        if (wxUnionid != null) {
            user.setWxUnionid(wxUnionid);
        }
        userService.updateById(user);
        log.info("用户绑定微信成功: {}", user.getUsername());
    }

    public void bindMiniProgram(Long userId, String miniProgramOpenid) {
        User user = userService.getById(userId);
        // 检查小程序是否已被绑定
        LambdaQueryWrapper<User> miniProgramQueryWrapper = new LambdaQueryWrapper<>();
        miniProgramQueryWrapper.eq(User::getMiniProgramOpenid, miniProgramOpenid);
        if (userService.getOne(miniProgramQueryWrapper) != null) {
            throw new BusinessException(ErrorCode.WX_MP_ALREADY_BIND);
        }
        user.setMiniProgramOpenid(miniProgramOpenid);
        userService.updateById(user);
        log.info("用户绑定小程序成功: {}", user.getUsername());
    }

    public User getUserById(Long userId) {
        return userService.getById(userId);
    }

    public User getUserByUsername(String username) {
        return userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
    }

    public IPage<User> getUserList(Integer page, Integer size) {
        Page<User> userPage = new Page<>(page, size);
        return userService.page(userPage);
    }

    public AdminDto.LoginResponse adminLogin(UserDto.LoginRequest loginRequest) {
        String username = loginRequest.getUsername();
        String password = loginRequest.getPassword();

        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getUsername, username)
                .or()
                .eq(Admin::getEmail, username)
                .or()
                .eq(Admin::getPhone, username);

        Admin admin = adminMapper.selectOne(queryWrapper);
        if (admin == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        if (!DigestUtil.bcryptCheck(password, admin.getPassword())) {
            throw new BusinessException(ErrorCode.USER_PASSWORD_ERROR);
        }
        // 构建响应
        AdminDto.LoginResponse response = new AdminDto.LoginResponse();
        response.setToken(jwtUtil.generateToken(admin.getId(), admin.getUsername()));
        response.setUserId(admin.getId());
        response.setUsername(admin.getUsername());
        response.setEmail(admin.getEmail());
        response.setPhone(admin.getPhone());
        response.setAvatar(admin.getAvatar());
        return response;
    }

    public Admin adminRegister(UserDto.RegisterRequest registerRequest) {
        String username = registerRequest.getUsername();
        String email = registerRequest.getEmail();
        String phone = registerRequest.getPhone();
        String password = registerRequest.getPassword();
        // 检查用户名是否已存在
        LambdaQueryWrapper<Admin> usernameQueryWrapper = new LambdaQueryWrapper<>();
        usernameQueryWrapper.eq(Admin::getUsername, username);
        if (adminMapper.selectOne(usernameQueryWrapper) != null) {
            throw new BusinessException(ErrorCode.USER_NAME_ALREADY_EXISTS);
        }
        // 检查邮箱是否已存在
        if (email != null) {
            LambdaQueryWrapper<Admin> emailQueryWrapper = new LambdaQueryWrapper<>();
            emailQueryWrapper.eq(Admin::getEmail, email);
            if (adminMapper.selectOne(emailQueryWrapper) != null) {
                throw new BusinessException(ErrorCode.USER_EMAIL_EXISTS);
            }
        }
        // 检查手机号是否已存在
        if (phone != null) {
            LambdaQueryWrapper<Admin> phoneQueryWrapper = new LambdaQueryWrapper<>();
            phoneQueryWrapper.eq(Admin::getPhone, phone);
            if (adminMapper.selectOne(phoneQueryWrapper) != null) {
                throw new BusinessException(ErrorCode.USER_PHONE_EXISTS);
            }
        }
        // 创建用户
        Admin admin = new Admin();
        admin.setUsername(username);
        admin.setEmail(email);
        admin.setPhone(phone);
        admin.setPassword(DigestUtil.bcrypt(password));
        admin.setCreatedAt(LocalDateTime.now());
        adminMapper.insert(admin);
        log.info("管理员注册成功: {}", username);
        return admin;
    }

    /**
     * 用户退出登录
     * @param token JWT token
     */
    public void logoutUser(String token) {
        // 将token加入黑名单
        String key = RedisConstant.JWT_BLACKLIST_PREFIX + token;
        long expiration = jwtUtil.extractExpiration(token).getTime() - System.currentTimeMillis();
        if (expiration > 0) {
            RedisUtil.set(key, "blacklisted", expiration, TimeUnit.MILLISECONDS);
        }
        log.info("用户退出登录成功");
    }

    /**
     * 管理员退出登录
     * @param token JWT token
     */
    public void logoutAdmin(String token) {
        // 将token加入黑名单
        String key = RedisConstant.JWT_BLACKLIST_PREFIX + token;
        long expiration = jwtUtil.extractExpiration(token).getTime() - System.currentTimeMillis();
        if (expiration > 0) {
            RedisUtil.set(key, "blacklisted", expiration, TimeUnit.MILLISECONDS);
        }
        log.info("管理员退出登录成功");
    }

    /**
     * 获取管理员信息
     * @param adminId 管理员ID
     * @return 管理员信息
     */
    public Admin getAdminInfo(Long adminId) {
        return adminMapper.selectById(adminId);
    }
}